Software executable files are typically generated by compiling separate host objects, where each host object includes a respective portion of source code or host code (e.g., written in a high-level language such as C, C++, etc.). The executable file generated by the compiler includes object code that can be executed by a central processing unit (CPU). More recently, host systems including a CPU and a graphics processing unit (GPU) have begun to take advantage of the parallel processing capability of the GPU to perform tasks that would otherwise be performed by the CPU. The GPU executes device code, whereas the CPU executes host code. The device code is typically embedded in the host code as a single file, thus creating a heterogeneous compiler environment.
Conventional host linkers or compilers generate an executable file from multiple host objects. However, these conventional host linkers are unable to link device code embedded in multiple host objects, and therefore, require any device code to be embedded in single host object. For example, conventional host linkers can create an executable file from a first host object containing only host code (for execution by the CPU) and a second host object containing host code (for execution by the CPU) and device code (for execution by the GPU). However, conventional host linkers are unable to create an executable file from multiple host objects each containing respective host code (for execution by the CPU) and respective device code (for execution by the GPU) since the conventional host linkers are unable to properly link the respective device code embedded in each of the host objects.